/*-------------------------------------------------------------------------
***************** Modification History ***********************************
   @doc
   @module Card.c - Card account number entry functionality |
   @end

$Log: /SoftPay/SPK2SIM/Source/Card/card.c $
**************************************************************************

   Copyright (C) 1999 by VeriFone, Inc.

   All rights reserved.  No part of this software may be reproduced,
   transmitted, transcribed, stored in a retrieval system, or translated
   into any language or computer language, in any form or by any means,
   electronic, mechanical, magnetic, optical, chemical, manual or otherwise,
   without the prior written permission of VeriFone, Inc.

---------------------------------------------------------------------------*/

#include <project.h>

//#include <beetle.h>
//#include <beetleplug.h>

#ifdef CARD_DEFINED

#define VSCARD_C

#include <aclconio.h>
#include <message.h>
#include <applidl.h>
#include <acldev.h>
#include <aclascii.h>
#include <aclstr.h>
#include <string.h>
#include <actutil.h>
#include <power.h>

/** /#define DEBUG_VSCARD*/
//#ifdef DEBUG_VSCARD
#define DEBUG_95
//#endif

#include <define.h>
#include <ui.h>
#include <tct.h>
#include <pct.h>
#include <trt.h>
#include <cdt.h>
#include <tblutil.h>
#include <hdt.h>
#include <iit.h>
#include <ict.h>
#include <funcids.h>
#include <msg.h>
#include <msgfuncs.h>
#include <init.h>
#include <print.h>
#include <tran.h>
#include <transact.h>
#include <table.h>
#include <mdlfuncs.h>
#include <date.h>
#include <passwd.h>
#include <card.h>
#include <cardmsg.h>
#include <sct.h>
#include <spdebug.h>
#include <gds.h>
#include <cdt.h>
#include <entry.h>
#include <stats.h>
#include <codesec.h>
#include <logo.h>
#include <menufunc.h>
#include <menus.h>
#include <pcounter.h>
#ifdef ICC_DEFINED
#include <libvoy.h>
#include <cardslot.h>
#endif
extern VS_BOOL gfPPadPresent;

FUNCTION_TABLE srCardFuncs[] = {
    {inImprintCardConfirm,                  IMPRINT_CARD_CONFIRM},
    {inEnterCardData,                       GET_CARD_FIELDS},
    {inSaleCardPresent,                     SALE_CARD_PRESENT},
    {inValidateSwipedCard,                  VALIDATE_SWIPED_CARD},
    {inValidateManualCardNo,                VALIDATE_MANUAL_NO},
    {inGetCardBin,                          GET_CARD_BIN},
    {inLoadGetCDTIndex,                     LOAD_GET_CDT},
    {inFastPayFlow,                         FAST_PAY},
    {inFraudControl,                        FRAUD_CONTROL},
    {inFC_ConfirmLast4,                     FC_CONFIRM_LAST4},
    {inFC_ConfirmDisplay,                   FC_CONFIRM_DISPLAY},
    {inFC_ConfirmBoth,                      FC_CONFIRM_BOTH},
    {inValidateCardEntryMethod,             VALIDATE_CARD_ENTRY},
    {inEditSCTOperation,                    EDIT_SCT},
    {inStartCardTxn,                        START_CARD_TRAN},
    {inManualEntryProcess,                  MANUAL_ENTRY_PROCESS},
    {inCardReadOperation,                   CARD_READ_OPERATION},
    {inDisplaySwipeCardInfo,                DISPLAY_SWIPE_CARD_INFO},
    {inDisplayCardTitle,                    DISPLAY_CARD_TITLE},
    {inDefaultFPSPrintOptionFunction,       FPS_PRT_OPTION_FUNCTION},
    {inCheckExpDate,                        CHECK_EXP_DATE},
    {inManualExpDate,                       MANUAL_EXP_DATE},
    {inValidateICCCard,                     VALIDATE_ICC_CARD},
    {NULL_PFI,                              CHECK_CARD_ENTRY},
    {0,                                     END_OF_FUNC_TABLE},

};

/*********************************************************************************************
* @func int | inAddCardFunctions |
*       Adds CARD functions to the flexi record.
*
* @rdesc return values.
* @flag int    |  VS_ERR, VS_ESCAPE or VS_SUCCESS
* @end
**********************************************************************************************/

int inAddCardFunctions(void) {
    int inCount = 0;

    /* Add CARD functions to the flexi record */
    do {
        if (inAddFunctionPointer(srCardFuncs[inCount].inFieldID, srCardFuncs[inCount].pinFunction) == VS_ERR)
            return (VS_ERR);
        inCount++;
    } while (srCardFuncs[inCount].inFieldID != END_OF_FUNC_TABLE);

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inGetCardBin |
*
*       Spaces purged from pchCardNum.  Test for Interac Debit and call inLoadGetCDTIndex() with
*       appropriate PAN.  Validate PAN length.  Validate LUHN if necessary.  Validate Manual only
*       flag based on transaction type.  Validate DEBIT processing.  Validate loyalty processing.
*
*       FIELD ID:       GET_CARD_BIN        0x0045
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
* @parm char *  | pchCardNum    |
* @parm unsigned    | fManual   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inGetCardBin(TRANSACTION_OBJECT* pobTran,char* pchCardNum,unsigned fManual) {
    int inCDTIndex,
    inCardLen;
    PFI_TO_PSZ pinLoadGetCDTIndex;

    //pdebug(("--inGetCardBin--"));

    if ((pinLoadGetCDTIndex = inGetFunctionPointer(LOAD_GET_CDT)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinLoadGetCDTIndex Error"));
        return(VS_ERR);
    }

    /* Remove Spaces from account number */
    purge_char(pchCardNum, ' ');

    inCDTIndex = pinLoadGetCDTIndex(pobTran, pchCardNum);

    if (inCDTIndex < 0) {
        if (inCDTIndex != VS_ESCAPE) {
            //pdebug (("inGetCardBin-1"));
            vdSGErrorMessage(NOT_SUPPORTED_ERR_MSG21);
        }
        return(inCDTIndex);
    }

    /* Check for proper card length */
    inCardLen = strlen(pchCardNum);

    if ((inCardLen < inGetMinPANDigit()) || (inCardLen > inGetMaxPANDigit())) {
        vdSGErrorMessage(INV_CARD_LEN_ERR_MSG21);
        return(VS_ERR);
    }

    if (fGetChkLuhn() == VS_TRUE)   /* Check Luhn */ {
        if (chk_luhn(pchCardNum) != 1) {
            vdSGErrorMessage(BAD_LUHN_MSG21);
            return (VS_ERR);
        }
    }


    if (fGetDebitFlag() != DEBIT && inGetType() == DEBIT_CARD) {
        //pdebug (("inGetCardBin-2"));
        vdSGErrorMessage(NOT_SUPPORTED_ERR_MSG21);
        return(VS_ERR);
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inValidateManualExpDate |
*
*       The expiry date validation routine (inValExpDate) expects the expiry
*       date in YYMM form. This data is stored in card track in YYMM format,
*       but the user enters it usually in MMYY format, so swap bytes 1 and 2
*       with bytes 3 and 4.
*
* @parm char *  | pchExpDate    |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inValidateManualExpDate(char* pchExpDate) {
    char chSwapper;

    //pdebug(("--inValidateManualExpDate(%s)--", pchExpDate));
    if (strlen(pchExpDate) != EXP_DATE_SIZE) {
        vdSGErrorMessage(INV_DATE_ERR_MSG);
        return (VS_ERR);
    }

    chSwapper = pchExpDate[0];
    pchExpDate[0] = pchExpDate[2];
    pchExpDate[2] = chSwapper;
    chSwapper = pchExpDate[1];
    pchExpDate[1] = pchExpDate[3];
    pchExpDate[3] = chSwapper;

    return(inValidateExpDate(pchExpDate));
}

/*********************************************************************************************
* @func int | inValidateManualCardNo |
*
*       Call inGetCardBin().  Set obTran->srBRec.inTranCardType base on inGetCDTType().
*       Set pobTran->srBRec.fManual.
*
*       FIELD ID:       VALIDATE_MANUAL_NO       0x0044
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
* @parm char *  | pchAcctNum    |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inValidateManualCardNo(TRANSACTION_OBJECT* pobTran,char* pchAcctNum) {
    int inResult;
    PFI_TO_PSZ_F      pinGetCardBin;
    //PFI pinGetCardBin;

    /* set the GDS manual entry flag */
    pobTran->srBRec.fManual = VS_TRUE;

    if ((pinGetCardBin = inGetFunctionPointer(GET_CARD_BIN)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinValSwiped Error"));
        return(VS_ERR);
    }

    //pdebug(("--inValidateManualCardNo--"));
    inResult = pinGetCardBin(pobTran, pchAcctNum, VS_TRUE);
    switch (inGetType()) {
    case DEBIT_CARD:
        pobTran->srBRec.inTranCardType = DEBIT_CARD; /* Set Debit Active */
        break;
    case PURCHASE_CARD:
        pobTran->srBRec.inTranCardType = PURCHASE_CARD; /* Set Purchase */
        break;
    case CREDIT_CARD:
        pobTran->srBRec.inTranCardType = CREDIT_CARD; /* Set Credit Active */
        break;
    case FLEET_CARD:
        pobTran->srBRec.inTranCardType = FLEET_CARD; /* Set Fleet Active */
        break;
    case EBT_CARD:
        /* Can Manually enter EBT Cards but still must have PINPad and Printer */
        pobTran->srBRec.inTranCardType = EBT_CARD; /* Set EBT Active */
        break;
    } /* end switch card type */

    if (inResult != VS_SUCCESS)
        return(inResult);

    if (fGetPinpadRequired()
#ifdef PINPAD_DEFINED
        && ((!gfPPadPresent) || (inGetPINPadType() == NO_PINPAD))
#endif /* PINPAD_DEFINED */
       ) {
        //vdDisplayMessageFromFile( TRANS_NOT_ALLWD_ERR_MSG, ERROR_MSG);
        vdSGErrorMessage(PINPAD_ERR_MSG21);
        INCREMENT_PINPAD_ERROR;
        return(VS_ERR);
    } /* end if CDT pinpad required */


    if (fGetPrntrRequired()) {
        if (inGetPrinterType() == NOPRINTER || !fGetEnablePrinter() || inChkPrinterStatus(&obPrinter) != VS_SUCCESS) {
            //vdDisplayMessageFromFile( TRANS_NOT_ALLWD_ERR_MSG, ERROR_MSG);

            vdSGErrorMessage(PRINTER_ERR_MSG21);
            return(VS_ERR);
        }
    } /* end if CDT printer required */


    return(VS_SUCCESS);
} /* inValidateManualCardNo() */

/*********************************************************************************************
* @func int | inEnterCardData |
*
*       Validates card number for manual entry or Swipe is set.
*       Also verifies whether manual entry allowed or not for this card range.
*       Checking of manual entry can only be done after CDT table is loaded.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inEnterCardData(TRANSACTION_OBJECT* pobTran) {
#ifndef IMAM_REMOVE
	int     inResult = VS_ERR;
    char szNull[21 + 1];
    int  inStatus;
    unsigned long   ulTimerCount;
    PFI pinValSwiped,
    pinValManual;
#ifdef ICC_DEFINED
    PFI pinValICC;
#endif


    PFI_TO_PFI_PIN pinTempFn;
    PFI_TO_PSZ_F  pinGetCardBin;
    //PFI pinGetCardBin;
    struct  TRACK srCardData;


#ifdef  COUNTER_DEFINED
    COUNTER_OBJECT obCounter;

    obCounter.inIndex = ALL_RECORDS;
#endif

    //pdebug(("--inEnterCardData--"));

    //BT_TRACE ('I', "Account #:");

    if (strlen(pobTran->srBRec.szPAN) > 0) {
        if ((pinGetCardBin = inGetFunctionPointer(GET_CARD_BIN)) == NULL_PFI) {
            /**/pdebug(("inGetFunctionPointer pinValSwiped Error"));/**/
            return(VS_ERR);
        }

        inResult = pinGetCardBin(pobTran, pobTran->srBRec.szPAN, VS_TRUE);
        if (inResult == VS_SUCCESS)
            vdDetermineCardType(pobTran, &srCardData);                  /* Card Detection */
        return(inResult);
    }
    // sets up the Menu
    if (inRunFunction(pobTran, START_CARD_TRAN) == VS_ERR)
        return (VS_ERR);

    if ((pinValSwiped = inGetFunctionPointer(VALIDATE_SWIPED_CARD)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinValSwiped Error"));
        return(VS_ERR);
    }

    if ((pinValManual = inGetFunctionPointer(VALIDATE_MANUAL_NO)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinValManual Error"));
        return(VS_ERR);
    }
#ifdef ICC_DEFINED
    if ((pinValICC = inGetFunctionPointer(VALIDATE_ICC_CARD)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinValManual Error"));
        return(VS_ERR);
    }
    if (Get_Card_State(CUSTOMER_CARD) != CARD_PRESENT)
        pobTran->inChipStatus = NOT_USING_CHIP;
#endif
    memset(szNull, NULL_CH, (int)sizeof(szNull));

    ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inGetIdleTimeOut(), TM_SECONDS);

    do {
        if (CHK_CARD_RDR()) {
            if ((pinTempFn = inGetFunctionPointer(CARD_READ_OPERATION)) == NULL_PFI)
                return(VS_ERR);
#ifdef COUNTER_DEFINED
            if (pinTempFn(pobTran, pinValSwiped, &inResult) == VS_ERR) {
                obCounter.inType = CARD_READ_ERROR;
                inIncCounter(&obCounter, 1);
                return (VS_ERR);
            } else {
                obCounter.inType = CARD_READ_ATTEMPTED;
                inIncCounter(&obCounter, 1);
            }
#else
            if (pinTempFn(pobTran, pinValSwiped, &inResult) == VS_ERR)
                return (VS_ERR);
#endif  /* COUNTER_DEFINED */
        }
#ifdef ICC_DEFINED
        else if ((Get_Card_State(CUSTOMER_CARD) == CARD_PRESENT) && (pobTran->inChipStatus == NOT_USING_CHIP)) {
            if ((pinTempFn = inGetFunctionPointer(CARD_READ_OPERATION)) == NULL_PFI)
                return(VS_ERR);
            if (pinTempFn(pobTran, pinValICC, &inResult) == VS_ERR)
                return(VS_ERR);
            pobTran->srBRec.inChipStatus = pobTran->inChipStatus;
            vdDetermineCardType(pobTran, &srCardData);                  /* Card Detection */
        }
#endif
        else if (act_kbd_pending_test(KEY_CANCEL))
            inResult = VS_ESCAPE;
        else if (KBHIT()) {
            if ((pinTempFn = inGetFunctionPointer(MANUAL_ENTRY_PROCESS)) == NULL_PFI)
                return(VS_ERR);
            inStatus = pinTempFn(pobTran, pinValManual, &inResult);
            if (inStatus < 0)
                return (inStatus);
        } else if (CHECK_TIMEOUT(ulTimerCount) == 0) {
            // KV1 20010118 - Allow terminal to go to sleep
            if (srGDS.fHandHeld && srGDS.fBatteryOperated && get_dock_status() == HANDHELD_UNDOCKED)
                vdTerminalSleep();
            else
                inResult = VS_ESCAPE;
        }
        /*
             *      Allow additional custom Card Entry
             */
        else
            inResult = inRunFunction(pobTran, CHECK_CARD_ENTRY);
    } while (inResult == VS_ERR);

    vdFlushKeyboardBuffer();

    if (inResult >= 0) {
        inResult = VS_SUCCESS;
	#ifdef IMAM_DBS
    //    if (inRunFunction(pobTran, DISPLAY_CARD_TITLE) == VS_ERR)
       //     return (VS_ERR);
      #endif 
    }

    vdClrNextLineEntry(); /* turn off */

    //pdebug(("--EXIT inEnterCarddata--"));
    return(inResult);
#endif //IMAM_REMOVE
	return VS_SUCCESS;
}

/*********************************************************************************************
* @func int | inValidateSwipedCard |
*
*       Clear pobTran->srBRec.fManual.  Read card information from card reader.  Validate data
*       length.  Call card_parse() with track priorty based on inGetTCTTrackNumber().
*       Call inValInteracDebit().  Call inGetCardBin().  Load loyalty information if neccessary.
*       Load fields pobTran->srBRec.szPAN and pobTran->srBKey.lnLast5.  Call vdDetermineCardType ().
*       Validate PINPAD present if necessary.  Process Track I and Track II information if necessary.
*       Validate Track II present for EBT and DEBIT.
*
*       FIELD ID:       VALIDATE_MANUAL_NO       0x0044
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inValidateSwipedCard(TRANSACTION_OBJECT* pobTran) {
#ifndef IMAM_REMOVE
    int inResult,
    inStatus = VS_SUCCESS;
    VS_BOOL fTrack2Valid = VS_FALSE;
    VS_BOOL fTrack1Valid = VS_FALSE;
    char chCardBuffer[CARD_SIZE + 1];
    char szTrackPriority[TRACKS_ALLOWED + 1];
    char* szTracksReq;
    struct  TRACK srCardData;
    //PFI pinGetCardBin;
    PFI_TO_PSZ_F  pinGetCardBin;
    PFI_PSZ pinCheckExpDate;

    pobTran->srBRec.fManual = VS_FALSE;

    if ((pinGetCardBin = inGetFunctionPointer(GET_CARD_BIN)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinValSwiped Error"));
        return(VS_ERR);
    }

    if ((pinCheckExpDate = inGetFunctionPointer(CHECK_EXP_DATE)) == NULL_PFI) {
        //pdebug (("inGetFunctionPointer pinValSwiped Error"));
        return(VS_ERR);
    }

    //pdebug(("--inValidateSwipedCard--"));

    /** changed 03/28/01 bruce_g1 - add VMAC card selection functionality **/
    inResult = inGetVMACSelectCArdData(chCardBuffer);
    if (!inResult)
        inResult = read(hCardReader, chCardBuffer, CARD_SIZE);

    if (inResult <= 6) {
        /* -- ba1: increment the card read error counter -- */
        INCREMENT_CARD_ERROR;
        vdSGErrorMessage(CARDREAD_ERR_MSG);
        return(VS_ERR);
    }

    strlcpy(szTrackPriority, szGetTracks(), TRACKS_ALLOWED);
    if (strpbrk(szTrackPriority, "123") == NULL_CH) {
        INCREMENT_CARD_ERROR;
        vdSGErrorMessage(INVALID_TCT_TRACK_MSG21);
        return(VS_ERR);
    }

    /* Parse card to get acct number to determine if debit
       handle card parse error */

    inResult = card_parse(chCardBuffer, &srCardData, szTrackPriority);
    if (inResult < 0) {
        INCREMENT_CARD_ERROR;
        vdGetCardParseError((long) inResult);
        return(VS_ERR);
    }

    /* inValInteracDebit (pobTran, &srCardData); */

    //pdebug(("card parse ret %d", inResult));
    if ((inResult = pinGetCardBin(pobTran, srCardData.acct, VS_FALSE)) <= VS_ERR)
        return(inResult);

    /* Gw fix from 2.5 - save service code for FPS no auth requires txn.*/
    strcpy(pobTran->szServiceCode, srCardData.type);
    strcpy(pobTran->srBRec.szPAN, srCardData.acct);
    strcpy(pobTran->srBRec.szExpDate, srCardData.exp);

    /* Form the Last 5 Acct # to Key Structure */
    //strlcpy(pobTran->srBKey.SAcctNum,&pobTran->srBRec.szPAN[strlen(pobTran->srBRec.szPAN) - 5],(FIVE_DIGIT_ACCT + 1));
    pobTran->srBKey.lnLast4 = str2long(&pobTran->srBRec.szPAN[strlen(pobTran->srBRec.szPAN) - LAST4_DIGIT_ACCT]);

    vdDetermineCardType(pobTran, &srCardData);                  /* Card Detection */

    if (fGetPinpadRequired()
#ifdef PINPAD_DEFINED
        && ((!gfPPadPresent) || (inGetPINPadType() == NO_PINPAD))
#endif /* PINPAD_DEFINED */
       ) {
        //vdDisplayMessageFromFile( TRANS_NOT_ALLWD_ERR_MSG, ERROR_MSG);
        vdSGErrorMessage(PINPAD_ERR_MSG21);
        INCREMENT_PINPAD_ERROR;
        return(VS_ERR);
    } /* end if CDT pinpad required */


    if (fGetPrntrRequired()) {
        if (inGetPrinterType() == NOPRINTER || !fGetEnablePrinter() || inChkPrinterStatus(&obPrinter) != VS_SUCCESS) {
            //vdDisplayMessageFromFile( TRANS_NOT_ALLWD_ERR_MSG, ERROR_MSG);

            vdSGErrorMessage(PRINTER_ERR_MSG21);
            return(VS_ERR);
        }
    } /* end if CDT printer required */



    if ((inResult = pinCheckExpDate(pobTran->srBRec.szExpDate)) <= VS_ERR)
        return(inResult);


    szTracksReq = szGetTracksRequired();

    if (strpbrk(szTrackPriority, "1") != NULL_CH) {
        inResult = card_parse(chCardBuffer, &srCardData, "1");

        if (inResult == 1) {
            inStatus = inCheckTrackOneData(&srCardData, inResult);
            if (inStatus == VS_ERR) {
                /* If we are not also reading track 2 or 3 OR track 1 is */
                /* required in the CDT then error out */
                if ((strpbrk(szTrackPriority, "23") == NULL_CH) || (strpbrk(szTracksReq, "1") != NULL_CH))
                    return VS_ERR;        /* Error Message is being set in inChecTranOneData */
            } else {
                fTrack1Valid = VS_TRUE;
                memcpy(pobTran->srBRec.stT1Data, (char *) srCardData.track, TRACK1_SIZE);/* Store Track 1  */
                pobTran->srBRec.fT1Data = VS_TRUE;
                strcpy(pobTran->srBRec.szCHolder, srCardData.name);
                pobTran->srBRec.fCHolder = VS_TRUE;
            }
        } else {
            /* If we are not also reading track 2 or 3 OR track 1 is */
            /* required in the CDT then error out */
            if ((strpbrk(szTrackPriority, "23") == NULL_CH) || (strpbrk(szTracksReq, "1") != NULL_CH)) {
                vdGetCardParseError((long) inResult);
                return VS_ERR;
            }
        }
    } /* end if reading track 1 */


    if (fTrack1Valid == VS_FALSE) {
        strcpy(pobTran->srBRec.szCHolder, "");
        pobTran->srBRec.fCHolder = VS_FALSE;
    }


    if (strpbrk(szTrackPriority, "2") != NULL_CH) {
        inResult = card_parse(chCardBuffer, &srCardData, "2");
        //pdebug(("card parse ret %d", inResult));
        inStatus = inCheckTrackTwoData(&srCardData, inResult);
        if (inStatus == VS_ERR) {
            /* If we don't have track 1 or are not about to read track 3, error out */
            if ((fTrack1Valid == VS_FALSE) && (strpbrk(szTrackPriority, "3") == NULL_CH))
                return VS_ERR;    /* Error Message is being set in inChecTranOneData */

            /* They are requiring Track 2 for this card */
            if (strpbrk(szTracksReq, "2") != NULL_CH)
                return VS_ERR;
        } else {
            fTrack2Valid = VS_TRUE;
            //pdebug(("Track2Valid"));
            memcpy(pobTran->srBRec.stT2Data, (char *) srCardData.track, TRACK2_SIZE);/* Store Track 2  */
            pobTran->srBRec.fT2Data = VS_TRUE;
        }
    } /* end if reading track 2 */


    if (strpbrk(szTrackPriority, "3") != NULL_CH) {
        inResult = card_parse(chCardBuffer, &srCardData, "3");
        //pdebug(("card parse ret %d", inResult));
        inStatus = inCheckTrackThreeData(&srCardData, inResult);
        if (inStatus == VS_ERR) {
            if ((fTrack1Valid == VS_FALSE) && (fTrack2Valid == VS_FALSE))
                return VS_ERR;    /* Error Message is being set in inChecTranOneData */

            /* They are requiring Track 3 for this card */
            if (strpbrk(szTracksReq, "3") != NULL_CH)
                return VS_ERR;
        } else {
            //pdebug(("Track3Valid"));
            memcpy(pobTran->stT3Data, (char *) srCardData.track, TRACK3_SIZE);/* Store Track 3  */
        }
    } /* end if reading track 3 */
#endif //IMAM_REMOVE
    return (VS_SUCCESS);
} /* end func inValidateSwipedCard() */


/*********************************************************************************************
* @func int| inValidateICCCard |
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inValidateICCCard(TRANSACTION_OBJECT* pobTran) {
    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func void | vdDetermineCardType |
*
*       This functions calls a func to set if card is debit/credit.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
* @parm TRACK *     | psrCardData   |
*
* @rdesc VOID
* @end
**********************************************************************************************/

void vdDetermineCardType(TRANSACTION_OBJECT* pobTran,struct TRACK* psrCardData) {
    /** pdebug(("--vdDetermineCardType--"));**/

    /*
        if (pobTran->fInteracDebit == VS_TRUE)
            return;
    */
    switch (inGetType()) {
    case DEBIT_CARD:
        pobTran->srBRec.inTranCardType = DEBIT_CARD; /* Set Debit Active */
        break;
    case PURCHASE_CARD:
        pobTran->srBRec.inTranCardType = PURCHASE_CARD; /* Set Purchase Active */
        break;
    case CREDIT_CARD:
        pobTran->srBRec.inTranCardType = CREDIT_CARD; /* Set Credit Active */
        break;
    case EBT_CARD:
        pobTran->srBRec.inTranCardType = EBT_CARD; /* Set EBT Active */
        break;
    case FLEET_CARD:
        pobTran->srBRec.inTranCardType = FLEET_CARD; /* Set Fleet Active */
        break;
    case LOYCREDIT_CARD:
    case LOYALTY_CARD:
        pobTran->srBRec.inTranCardType = LOYALTY_CARD; /* Set Credit Active */
    }

    return; /* Return void in all instances */
}


/*********************************************************************************************
* @func int | inValInteracDebit |
*
*       This functions looks for the Interac Designator Codes.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
* @parm TRACK *     | psrCardData   |
*
* @rdesc Return values.
* @flag int    |  VS_TRUE       |
* @flag int    |  VS_FALSE      |
* @end
* @end
**********************************************************************************************/

/* This code has been removed from the base, per Jim 08/01/00 - mdm
int inValInteracDebit (TRANSACTION_OBJECT *pobTran, struct TRACK *psrCardData)

{
    char psLangCode;

*   pdebug(("-- inValInteracDebit --"));** /

    if (fIsINTERAC(psrCardData->type))
    {
        psLangCode = psrCardData->track[strlen(psrCardData->track)-1];
    //pdebug(("LangCode=%c",psLangCode));
        if(psLangCode == '2')    If this is a  French Card,
            pobTran->srBRec.inLCTIndex = 1;      set receipt flag to French '1'
        else
            pobTran->srBRec.inLCTIndex = 0;      else receipt flag to English 0
        pobTran->fLanguageOnSwipe = VS_TRUE;

    *   pdebug(("Language Code = %c", (pobTran->srBRec.inLCTIndex + 0x30)));** /

        pobTran->srBRec.inTranCardType = DEBIT_CARD;  Set Debit Active
        pobTran->fInteracDebit = VS_TRUE;  Set Debit Active
        return(VS_TRUE);   Hit a designator, card is an interac debit card
    }

    return(VS_FALSE);    Card check failed, card is not if interac debit
}
*/

/********************************************************************************************
* @func int | inValidateCardEntryMethod |
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inValidateCardEntryMethod(TRANSACTION_OBJECT* pobTran) {
    int inEntryMode;


    /*
     *      Host Comm Type must be ISDN to run TEST TRANSCTION and transaction must be allowed in ICT.
     */
    if (pobTran->srBRec.inCode == ISDN_TEST_TRANSACTION) {
        if (inValidateISDN_TEST_TRANSACTION() != VS_SUCCESS)
            return (VS_ERR);
    }

    inEntryMode = shGetCardMode(pobTran);

    if (pobTran->srBRec.fManual == VS_TRUE) {
        if (inEntryMode == READ_CARD_SWIPED) {
            vdSGErrorMessage(SWIPE_ONLY_ERR_MSG21);
            return (VS_ERR);
        }
    } else {
        if ((inEntryMode == READ_CARD_MANUAL)) {
            vdSGErrorMessage(MANUAL_ONLY_ERR_MSG21);
            return (VS_ERR);
        }
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inFraudControl |
*
*       This function prompts user for last 4 digits of acct
*       number and/or display MSR data. The function
*       applis to card swipe entry only.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ESCAPE     |
* @end
**********************************************************************************************/

int inFraudControl(TRANSACTION_OBJECT* pobTran) {
    int inFraudControlMode;

    inFraudControlMode = inGetFraudControl();

    if (pobTran->srBRec.inTranCardType == DEBIT_CARD || pobTran->srBRec.inTranCardType == EBT_CARD ||    /*JB4*/
        pobTran->inChipStatus == EMV_CARD)
        return(VS_SUCCESS);

    if (pobTran->srBRec.fCloseTabSameCard)
        return(VS_SUCCESS);

    if (inFraudControlMode != NO_FC) {
        if (inFraudControlMode == FC_LAST4 || inFraudControlMode == FC_BOTH) {
            if (inFC_ConfirmLast4(pobTran) != VS_SUCCESS)
                return (VS_ESCAPE);
        }
        if (inFraudControlMode == FC_DISPLAY || inFraudControlMode == FC_BOTH) {
            if (inFC_ConfirmDisplay(pobTran) != VS_SUCCESS)
                return (VS_ESCAPE);
        }
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inFC_ConfirmLast4 |
*
*       This function prompts user for last 4 digits of acct
*       number.  The function applies to card swipe entry only.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ESCAPE     |
* @end
**********************************************************************************************/

int inFC_ConfirmLast4(TRANSACTION_OBJECT* pobTran) {
    int inResult = VS_SUCCESS;

    // pdebug(("--inFC_ConfirmLast4--"));

    if (pobTran->srBRec.fManual == VS_FALSE) {
        vdFlushKeyboardBuffer();
        vdClearNonTitleLines();
        do {
            inResult = inValidateLast4Digits(pobTran->srBRec.szPAN);
        } while (inResult != VS_ESCAPE && inResult != VS_SUCCESS);
        vdSGErrorMessage(0L);
    }

    return (inResult);
}

/*********************************************************************************************
* @func int | inFC_ConfirmDisplay |
*
*       This function displays MSR data. The function
*       applies to card swipe entry only.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ESCAPE     |
* @end
**********************************************************************************************/

int inFC_ConfirmDisplay(TRANSACTION_OBJECT* pobTran) {
    char chAccountNumber[PAN_SIZE + 1];

    if (pobTran->srBRec.fManual == VS_FALSE) {
        strcpy(chAccountNumber, pobTran->srBRec.szPAN); /* get card swipe number */
        if (obDisp.inDO_ChooseOne(chAccountNumber, (char *) pchGetMsg(CONFIRM_MSG15), (char *) pchGetMsg(YESNO_MSG5x), 2, NULL_PFI) != KEY_YES)
            return(VS_ESCAPE);
    }

    return (VS_SUCCESS);
}


/*********************************************************************************************
* @func int | inFC_ConfirmBoth |
*
*       This function prompts user for last 4 digits of acct
*       number.  The function applies to card swipe entry only.
*
*       AND
*
*       This function displays MSR data. The function
*       applies to card swipe entry only.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ESCAPE     |
* @end
**********************************************************************************************/

int inFC_ConfirmBoth(TRANSACTION_OBJECT* pobTran) {
    if (inFC_ConfirmLast4(pobTran) != VS_SUCCESS)
        return (VS_ESCAPE);

    if (inFC_ConfirmDisplay(pobTran) != VS_SUCCESS)
        return (VS_ESCAPE);

    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inValidateLast4Acct |
*
*       This function checks if last 4 digits entered by user
*       matches last 4 digits read from card swipe.
*
* @parm char *  | pchAccount    |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inValidateLast4Digits(char* pchAccount) {
    int inResult,
    i;
    char szLast4Digits[5];
    int inRowLim = inGetRowLim();

    // pdebug(("--inValidateLast4Digits--"));
    obDisp.inStringMinLength = 4;
    inResult = inEnterWithMessage(LAST_4DIGITS_MSG17, SCROLL_DISPLAY_FALSE, szLast4Digits, INPUT_NUMS, 4, inValStringMinLength);
    window(obDisp.inHomeCol, obDisp.inTitleLine, inRowLim, obDisp.inCharsPerColumn);

    if (inResult <= 0)
        return (VS_ESCAPE);

    /* advanced string pointer to last 4 digits */
    i = strlen(pchAccount) - 4;
    if (strncmp(pchAccount + i, szLast4Digits, 4) != 0) {
        vdDisplayWarningMsg(BAD_ACCT_LEN_ERR_MSG);
        return(VS_ERR);
    } else
        return (VS_SUCCESS);
}
/*********************************************************************************************
* @func void |  vdSetCustomFPSPrintOption |
*
*       Runs the custom function which determines if a transaction
*       qualifies for Fast Payment.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @end
**********************************************************************************************/

static int inSetCustomFPSPrintOption(TRANSACTION_OBJECT* pobTran) {
    return (inRunFunction(pobTran, FPS_PRT_OPTION_FUNCTION));
}

int inDefaultFPSPrintOptionFunction(TRANSACTION_OBJECT* pobTran) {
    return(VS_SUCCESS);
}



/*********************************************************************************************
* @func int | inFastPayFlow |
*
*       This function determines FPS requirements for authorization,
*       printing, and signature, for FPS qualified transactions.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ERR        |
* @end
**********************************************************************************************/

int inFastPayFlow(TRANSACTION_OBJECT* pobTran) {
    long int lnTransAmount;
    int inRetVal = VS_SUCCESS;

    /* if transaction does not qualify for Fast Pay, exit */
    if (fFPSQualified(pobTran)) {
        /* SET AUTHORIZATION OPTIONS */

        /* no authorization required, if
           - FPS Type = Floor Limit
           - FPS Type = FPS_VISA_EXP, trans amt <= floor amt */
        if (fFPSNoAuthRequired(pobTran)) {
            /* overwrite TRT value to create Offline transaction */
            vdSetOffline(pobTran, VS_TRUE);
            pobTran->srBKey.fOffline = VS_TRUE;
            pobTran->fFloorLimit = VS_TRUE;
        }

        /* SET PRINT OPTIONS */

        /* initialize batch record Print Option to the value set up in the TCT,
           update as needed to meet FPS requirements */
        pobTran->srBRec.inPrintOption = inGetPrintOption();
        lnTransAmount = pobTran->srBKey.lnTotalOfTransactionAmount;

        /* must print merchant and customer receipts, if
           - FPS Type = Floor Limit, or
           - FPS Type = FPS_AX_QRS, or
           - FPS Type = FPS_VISA_EXP, receipt amt > 0, trans amt > floor amt
           need to print customer copy only, if
           - FPS Type = FPS_VISA_EXP, receipt amt > 0,
             trans amt > receipt amt, trans amt <= floor amt */
        switch (inGetFPSType()) {
        case FPS_FLOOR:
        case FPS_AX_QRS:
            pobTran->srBRec.inPrintOption = PRT_BOTH_CONF_CUSTCOPY;
            break;
        case FPS_VISA_EXP:
            if (lnGetReceiptLimitAmount() > 0) {
                if (lnTransAmount > lnGetFloorLimitAmount())
                    pobTran->srBRec.inPrintOption = PRT_BOTH_CONF_CUSTCOPY;

                if ((lnTransAmount > lnGetReceiptLimitAmount()) && (lnTransAmount <= lnGetFloorLimitAmount())) {
                    if ((pobTran->srBRec.inPrintOption == PRT_NONE) || (pobTran->srBRec.inPrintOption == PRT_PROMPT) || (pobTran->srBRec.inPrintOption == PRT_CUST))
                        pobTran->srBRec.inPrintOption = PRT_CUST;
                    else
                        pobTran->srBRec.inPrintOption = PRT_BOTH_CONF_CUSTCOPY;
                }
            }
            break;

        case FPS_CUSTOM:
            inRetVal = inSetCustomFPSPrintOption(pobTran);
            break;

        default:
            break;
        }

        /* SET SIGNATURE OPTIONS */

        /* CDT signature line flag for credit cards is enabled upon download,
           update to no signature required, if
           - FPS Type is not equal to Floor Limit */
        if (inGetFPSType() != FPS_FLOOR)
            vdSetSignLine(0);
    }

    return(inRetVal);
}

/*********************************************************************************************
* @func int | inSaleCardPresent |
*
*       This function sets the AVS code for prompting depending
*       on card present.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @flag int    |  VS_ESCAPE     |
* @end
**********************************************************************************************/

int inSaleCardPresent(TRANSACTION_OBJECT* pobTran) {
    signed int inRetVal = VS_SUCCESS;

    pdebug(("--inSaleCardPresent--"));
    	
    if (pobTran->srBRec.fManual == VS_TRUE && inGGCode() == SALE) {
        if (fGetCardPresent()) {
            /* Card present; retain current transaction type   */
            /* if CARD PRESENT prompt  */
            inRetVal = obDisp.inDO_ChooseOne(NULL, pchGetMsg(CARD_PRESENT_MSG15), pchGetMsg(YESNO_MSG5x), 2, NULL_PFI);

            if (inRetVal == KEY_YES) {
                pobTran->fCardPresent = VS_TRUE;
                vdSetAVS(AVS_ZIPCODE);
                inRetVal = VS_SUCCESS;
            } else if (inRetVal == VS_ESCAPE) {
                vdSGErrorMessage(TXN_CANCELLED);
                inRetVal = VS_ESCAPE;
            } else if (inRetVal == KEY_NO) {
                TRANSACTION_OBJECT obTran;

                pdebug(("szTranAbbrev=%s", pobTran->srBRec.szTranAbbrev));
                pobTran->srBRec.inCode = PHONE;
                pobTran->inTransactionCode = PHONE;
                vdSGCode(PHONE);
                pobTran->srBRec.lnMessage = PHONE_MSG;
                /* Load TRT locally */
                inLoadTRTRec(&obTran, pobTran->srBRec.inCode);
                strcpy(pobTran->srBRec.szTranAbbrev, szGetTranAbbrev(&obTran));
                pdebug(("szGetTranAbbrev=%s", szGetTranAbbrev(&obTran)));
                pdebug(("szTranAbbrev=%s", pobTran->srBRec.szTranAbbrev));
                inRetVal = VS_SUCCESS;
            }
        } else {
            vdSetAVS(NO_AVS);
            inRetVal = VS_SUCCESS;
        }
    }
    return(inRetVal);
}

/*********************************************************************************************
* @func int | inImprintCardConfirm |
*
*       This function display imprint card message on
*       manual card entry only.
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @end
**********************************************************************************************/

int inImprintCardConfirm(TRANSACTION_OBJECT* pobTran) {
    if (inGetImprintCardConfirm() && (pobTran->srBRec.fManual == VS_TRUE) && (pobTran->srBRec.fWebTran == VS_FALSE)) {
        vdClearNonTitleLines();
        vdDispMsgAt(IMPRINT_CARD_MSG21, obDisp.inHomeCol, obDisp.inStatusLine - 1, CLR_EOL);
        vdDispMsgAt(PRESS_KEY_MSG21, obDisp.inHomeCol, obDisp.inStatusLine, CLR_EOL);

        /* accept any key, even CLEAR */
        if (inWaitKey(inGetIdleTimeOut()) == KEY_CANCEL)
            return (VS_ESCAPE);
        vdClearNonTitleLines();
        return (VS_SUCCESS);
    }

    return(VS_SUCCESS);
}

int CARD_CODE_CHECK(char* a,char* b,short * c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);
    return 1;
}



/*********************************************************************************************
* @func int | inGetCVV2 |
*
*       This function will prompt for CVV2 information
*
* @parm TRANSACTION_OBJECT *    | pobTran   |
*
* @rdesc Return values.
* @flag int    |  VS_SUCCESS    |
* @end
**********************************************************************************************/
#ifndef  REMOVE_CORE_GET_CVV2
int inGetCVV2(TRANSACTION_OBJECT* pobTran) {
    char szCVV2Code[CVV2_SIZE + 1];
    signed int inResult = VS_ERR;
    unsigned long ulTimerCount;
    char* chNull = 0;

    if (inGetCVV_II() == NO_CVV2 || (pobTran->srBRec.fManual == VS_FALSE) || pobTran->srBKey.fOffline)
        return(VS_SUCCESS);
    if ((inGetCVV_II() == CVV2_CARD_NOT_PRESENT) && fGetCardPresent() && pobTran->fCardPresent)
        return(VS_SUCCESS);

    if ((inGetCVV_II() == CVV2_CARD_NOT_PRESENT) && (fGetCardPresent() == VS_FALSE)) {
        vdDisplayMessageFromFile(CDT_CVV2_CONFLICT_ERR_MSG, ERROR_MSG);
        return(VS_ESCAPE);
    } else {
        memset(szCVV2Code, NULL_CH, (int)sizeof(szCVV2Code));

        ulTimerCount = set_itimeout(NO_CLOCK_HANDLE inGetPPTimeOut(), TM_SECONDS);
        do {
            inResult = inEnterWithMessage(CVV2_VCODE_MSG, SCROLL_DISPLAY_TRUE, szCVV2Code, INPUT_NUMS, CVV2_SIZE, NULL_PFI);
            /* press escape will assign 0 to inResult */
            if (inResult >= 0) {
                if (inResult == 0) {
                    if ((inResult = obDisp.inDO_ChooseOne(chNull, (char *) pchGetMsg(CODE_ON_BACK_MSG), (char *) pchGetMsg(NO_XREAD_MSG), 2, NULL_PFI)) == KEY_CODE_ON_BACK_NO) {
                        pobTran->chCVV2PresenceIndicator = CVV2_NOT_ON_BACK;
                        strcpy(pobTran->szCVV2Value, " ");
                        inResult = VS_SUCCESS;
                    } else if (inResult == KEY_CODE_ON_BACK_XREAD) {
                        pobTran->chCVV2PresenceIndicator = CVV2_ILLEGIBLE;
                        strcpy(pobTran->szCVV2Value, " ");
                        inResult = VS_SUCCESS;
                    } else {
                        inResult = VS_ERROR;
                        // gu_clr_state = VS_FALSE;   /* so that CLEAR will not cause terminal to idle */
                    }
                } else {
                    /* process and build packet here */
                    pobTran->chCVV2PresenceIndicator = CVV2_VALUE_PRESENCE;
                    strlcpy(pobTran->szCVV2Value, szCVV2Code, CVV2_SIZE);
                    inResult = VS_SUCCESS;
                }
            } else {
                inResult = VS_ESCAPE;
                /* gu_clr_state = VS_TRUE; */
            }
        } while (inResult == VS_ERROR) ;
    }
    return(inResult);
}

#endif /* #ifndef  REMOVE_CORE_GET_CVV2 */


/*********************************************************************************************
* @func int | inStartCardTxn |
*
* This function starts a card based or manual entry based transaction with the
* approp: messages.
*
* @parm void    | void|
*
* @rdesc Return values.
* @ VS_SUCCESS  |  VS_SUCCESS   |
* @ VS_ERROR    |  VS_ERROR     |
* @end
**********************************************************************************************/

int inStartCardTxn(TRANSACTION_OBJECT* pobTran) {
#ifndef IMAM_REMOVE
    /* Don't need this because its being done in inCardReadOperation() */
    /* and if they allow manual entry of Debit cards (LAC) then they */
    /* probably don't care about the printer anyway and we are only */
    /* checking refunds.  mdm - 07/14/00 */
    //   if ((inGetPrinterType() == NOPRINTER  || !fGetEnablePrinter()) &&
    //      inGGCode() == REFUND_DEBIT)
    //  {
    //        vdDisplayMessageFromFile( TRANS_NOT_ALLWD_ERR_MSG, ERROR_MSG);
    //      return(VS_ERR);
    //  }

    if ((inGGCode() != PHONE) && (CHK_CARD_RDR() == 0)
#ifdef ICC_DEFINED
        && (Get_Card_State(CUSTOMER_CARD) != CARD_PRESENT)
#endif
       ) {
        if (pobTran->fHHSwipeOnly)
        	{ 	
        	#ifdef IMAM_DBS 
			#else
            		vdDisplayMessageFromFile(HH_SWIPE_MSG21, ENTRY_MSG);
			#endif

        	}
        else{
			#ifdef IMAM_DBS 
			#else
            		vdDisplayMessageFromFile(SWIPE_MSG, ENTRY_MSG);
			#endif
        	}
#ifdef ICC_DEFINED
        if ((strcmp(srGDS.modelNo, "OMNI3350") == 0) || (strcmp(srGDS.modelNo, "OMNI3600") == 0) || (strcmp(srGDS.modelNo, "OMNI3750") == 0))
            vdDisplayMessageFromFile(INSERT_MSG21, ENTRY_MSG);
#endif
    }
    if (CHK_CARD_RDR() == 0
#ifdef ICC_DEFINED
        && (Get_Card_State(CUSTOMER_CARD) != CARD_PRESENT)
#endif
       )
        vdDisplayMessageFromFile(ACCT_MSG21, ENTRY_MSG);

    vdClearStatusMessage();
#endif //IMAM_REMOVE
    return (VS_SUCCESS);
}


int inCardReadOperation(TRANSACTION_OBJECT* pobTran,PFI_TO pinValSwiped,int* pinResult) {
#ifndef IMAM_REMOVE
    char szNull[21 + 1];

    memset(szNull, NULL_CH, (int)sizeof(szNull));

    //pdebug(("Card Read"));
    *pinResult = pinValSwiped(pobTran);

    if (*pinResult == VS_SUCCESS) {
		#ifdef IMAM_DBS
		#else
        if (inRunFunction(pobTran, DISPLAY_SWIPE_CARD_INFO) == VS_ERR)
            return(VS_ERR);
		#endif
    } else {
		        if (lnGGErrorMessage()) {
		            vdDisplayMessageFromFile(lnGGErrorMessage(), WARNING_MSG);
		            if (obDisp.inTitleLine == obDisp.inStatusLine || obDisp.inTitleLine == obDisp.inInputLine)
		                clrscr();
					
		            if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
				                char szNull[21 + 1];

				                memset(szNull, NULL_CH, (int)sizeof(szNull));
				                if ((getgrid() == 0) && (get_font_mode() == 2)) // 2 byte addressing scheme + 16x16 Font
				                {
				                    szNull[0] = 0x01;
				                    szNull[1] = 0x20;
				                } else
				                    szNull[0] = SPACE;
				                /* remove previous prompts so not scrolled after error */
								#ifdef IMAM_DBS
				                vdDisplayAt(obDisp.inHomeCol, (obDisp.inInputLine - 1), szNull, CLR_EOL);
				                vdDisplayAt(obDisp.inHomeCol, obDisp.inInputLine, szNull, CLR_EOL);
				                vdDisplayAt(obDisp.inHomeCol, obDisp.inCharsPerColumn, szNull, CLR_EOL);
							#endif	
				            	}
		            vdSGErrorMessage(0L);   /* Do not want to display this again */
					
		            if (inGGCode() != PHONE) {
			                if (pobTran->fHHSwipeOnly) {
								#ifdef IMAM_DBS
								#else
			                    vdGetMessageFromFile(HH_SWIPE_MSG21, szNull);
			                    vdDisplayAt(obDisp.inHomeCol, (obDisp.inInputLine - 1), szNull, CLR_EOL);
								#endif
			                	}
					 else{
						#ifdef IMAM_DBS
						#else
		                 	   	vdDisplayMessageFromFile(SWIPE_MSG, ENTRY_MSG);
						#endif
					 	}
#ifdef ICC_DEFINED
				if ((strcmp(srGDS.modelNo, "OMNI3350") == 0) || (strcmp(srGDS.modelNo, "OMNI3600") == 0) || (strcmp(srGDS.modelNo, "OMNI3750") == 0))
		                    vdDisplayMessageFromFile(INSERT_MSG21, ENTRY_MSG);
#endif
		            	}
					#ifdef IMAM_DBS
					#else
				            vdDisplayMessageFromFile(ACCT_MSG21, ENTRY_MSG);
					#endif
		        }   // if you have error message active
		        /* Clear Track Data on bad reads */
		        MEMCLR(pobTran->srBRec.stT1Data, TRACK1_SIZE);/* Clear Track 1  */
		        MEMCLR(pobTran->srBRec.stT2Data, TRACK2_SIZE);/* Clear Track 2  */
		        pobTran->srBRec.fT1Data = VS_FALSE;
		        pobTran->srBRec.fT2Data = VS_FALSE;
		        strcpy(pobTran->srBRec.szCHolder, szNull);
		    }   // end of error messsage handling
#endif //IMAM_REMOVE
    return (VS_SUCCESS);
}


int inDisplaySwipeCardInfo(TRANSACTION_OBJECT* pobTran) {
#ifndef IMAM_REMOVE
    int inFmtPANLen,
    inMsgLen;
    int inRow = obDisp. inInputLine,
    inCol,
    inDummyCol = 1;
    char szMsg[MESSAGE_SIZE + 1];
    char szFormattedPAN[FORMATTED_PAN_SIZE + 1];

    if (!pobTran->srBRec.fManual) {
        vdClearStatusMessage();
        strcpy(szFormattedPAN, pobTran->srBRec.szPAN);
        vdGetMessageFromFile(ACCT_MSG21, szMsg);
        inMsgLen = strlen(szMsg);
        inFmtPANLen = strlen(szFormattedPAN);

        vdDisplayAt(obDisp.inHomeCol, obDisp.inInputLine, szMsg, CLR_EOL);
        /* Calculate column based on 8x21 font and PAN Length */
        inCol = ((21 - inFmtPANLen) + 1);

        if (obDisp.blActionFontASC8x21) {
            if (obDisp.inTitleLine == obDisp.inStatusLine || obDisp.inTitleLine == obDisp.inInputLine)
                clrscr();

            /* force entire PAN to next line so scrolling of it makes sense */
            vdSetNextLineEntry();
            vdDisplayAt(inCol, obDisp.inInputLine + 1, szFormattedPAN, CLR_EOL);
        } else {
            /* Calculate row base on 4x8 font to 8x21 */
            vdCalculateCoord(GRID_4x8_TO_8x21, &inDummyCol, &inRow);
            vdDisplayAt_ASC8X21(inCol, inRow, szFormattedPAN, NO_CLEAR);
        }

        vdSetNextLineCleanup();
        vdClrNextLineEntry();
    } /* end if not manual entry */
#endif //IMAM_REMOVE
    return (VS_SUCCESS);
} /* end func inDisplaySwipeCardInfo() */


int inManualEntryProcess(TRANSACTION_OBJECT* pobTran,PFI_TO_PSZ pinValManual,int* pinResult) {
#ifndef IMAM_REMOVE
    int inStatus;
    char szAccountNumber[PAN_SIZE + 1];
    char szClearInput[EXP_DATE_SIZE + 1];
    PFI_TO pinManualExpDate;

    if ((pinManualExpDate = inGetFunctionPointer(MANUAL_EXP_DATE)) == NULL_PFI)
        return(VS_ERR);

    //pdebug(("KBHIT"));
    vdSetNextLineEntry(); /* force entry on line after prompt */

    *pinResult = inEnterWithMessage(ACCT_MSG21, SCROLL_DISPLAY_FALSE, szAccountNumber, INPUT_NUMS, PAN_SIZE, NULL);

    if (*pinResult >= 0) {
        *pinResult = pinValManual(pobTran, szAccountNumber);
        if (*pinResult >= 0) {
            strcpy(pobTran->srBRec.szPAN, szAccountNumber);
            /* Form the Last 4 Acct # to Key Structure */
            pobTran->srBKey.lnLast4 = str2long(&pobTran->srBRec.szPAN[strlen(pobTran->srBRec.szPAN) - LAST4_DIGIT_ACCT]);
        }
    } else {
        inStatus = *pinResult;
        return(inStatus);
    }

    /* PJ1 - Prompt for EXPDATE only if flag is on */
    if (*pinResult >= 0)
        *pinResult = pinManualExpDate(pobTran);
    if (*pinResult < 0) {
        if (lnGGErrorMessage()) {
            if (*pinResult != VS_ESCAPE) {
                vdDisplayMessageFromFile(lnGGErrorMessage(), WARNING_MSG);
                vdClearNonTitleLines();
            }
            vdSGErrorMessage(0L);

            if (inGGCode() != PHONE) {
                if (pobTran->fHHSwipeOnly)
                    vdDisplayMessageFromFile(HH_SWIPE_MSG21, ENTRY_MSG);
                else{
			#ifdef IMAM_DBS
			#else
                    vdDisplayMessageFromFile(SWIPE_MSG, ENTRY_MSG);
			#endif
                	}		
#ifdef ICC_DEFINED
                if ((strcmp(srGDS.modelNo, "OMNI3350") == 0) || (strcmp(srGDS.modelNo, "OMNI3600") == 0) || (strcmp(srGDS.modelNo, "OMNI3750") == 0))
                    vdDisplayMessageFromFile(INSERT_MSG21, ENTRY_MSG);
#endif
            }

            // Don't know why ENTRY_MSG works for above but not this
            // one so temporarily use STATUS_MSG here.
            // Bug # DP 4 / EM54890 - MM2
            vdDisplayMessageFromFile(ACCT_MSG21, STATUS_MSG);
        }
    } else {
        if (fGetManEntry()) {
            if (fGetManEntryPasswd())
                do {
                    *pinResult = inGetPwdFromUser(ACCESS_WITH_SUPER_PASSWORD, NO_PIT_INDEX);
                    //*pinResult = inGetAndValSuperManPwds(BOTH_PW);
                    if (*pinResult == VS_ERR) {
                        if (lnGGErrorMessage()) {
                            vdDisplayMessageFromFile(lnGGErrorMessage(), WARNING_MSG);
                            vdClearStatusMessage();
                            vdSGErrorMessage(0L);
                        }
                    }
                } while ((*pinResult != VS_ESCAPE) && (*pinResult != VS_SUCCESS));
        } else {
            vdDisplayMessageFromFile(MAN_ENTRY_MSG21, WARNING_MSG);
            *pinResult = VS_ESCAPE;
        }
    }

    /* AS1 - fix AM53390 PE21 - clear EXP DATE before currency prompt */
    memset(szClearInput, '\0', (int)sizeof(szClearInput));
    vdDisplayAt(obDisp.inHomeCol, obDisp.inInputLine, szClearInput, CLR_EOL);
#endif //IMAM_REMOVE
    return (VS_SUCCESS);
}

int inDisplayCardTitle(TRANSACTION_OBJECT* pobTran) {
#ifndef IMAM_REMOVE
    char szCardLabel[CLABEL_SIZE + 1];

    if (pobTran->srBRec.inTranCardType == DEBIT_CARD)
        vdGetMessageFromFile(DEBIT_MSG, szCardLabel);
    else
        strlcpy(szCardLabel, szGetCardLabel(), CLABEL_SIZE);
    vdDisplayTitle(EMPTY_STR_ERR_MSG, CLEAR_TITLE);
    if (obDisp.blActionFontASC8x21)
        vdDisplayAt(obDisp.inHomeCol, obDisp.inTitleLine, szCardLabel, NO_CLEAR);
    else
        vdDisplayAt_ASC8X21(obDisp.inHomeCol, obDisp.inTitleLine, szCardLabel, NO_CLEAR);
#endif //IMAM_REMOVE
    return (VS_SUCCESS);
}


int inCheckExpDate(char* pchExpDate) {
    int inResult = VS_SUCCESS;

    if (fGetExpDtReqd())
        inResult = inValidateExpDate(pchExpDate);

    return(inResult);
} /* end func inCheckExpDate() */


int inManualExpDate(TRANSACTION_OBJECT* pobTran) {
    int inResult = VS_SUCCESS;
    char chExpDate[EXP_DATE_SIZE + 1];

    if (fGetExpDtReqd()) {
        memset(chExpDate, NULL_CH, (int)sizeof(chExpDate));
        inResult = inEnterWithMessage(EXPDATE_MSG17, SCROLL_DISPLAY_TRUE, chExpDate, INPUT_NUMS, EXP_DATE_SIZE, inValidateManualExpDate);
        strcpy(pobTran->srBRec.szExpDate, chExpDate);
    }

    return(inResult);
} /* end func inManualExpDate() */


int inCheckCardSwipe() {
    /* Check if card swipe was acquired via VMAC */
    if (inCheckVMACCardSelect())
        return 1;
    else
        return (card_pending());
} /* end func inCheckCardSwipe() */


#undef VSCARD_C
#endif
